package cn.yto.print.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class AkcSignatureUtil {

    private static final String PROD_APP_ID = "64b9ecee4a184eada844a3369d40bf7d";
    private static final String PROD_APP_SECRET = "b04ce4c857384242a51c2a25950d35e7";

    private static final String UAT_APP_ID = "f4ee1e41f9dc4bd39eb8ad05cc2a0c4d";
    private static final String UAT_APP_SECRET = "7e88e9e89de94ec99d7817ff87ce5280";
    private static final String UAT_ACCESS_TOKEN = "8f597d0fb9084008be44e7cd7be65564";

    private static final String noncestr = "3cba0cd3e";
    private static final String version = "1.0";
    private static final String format = "json";
    private static final String interfaceName = "mengxiang.logistics.lews.getPrintInfoPdf";

    /**
     * 生成签名
     */
    public static String generateSignature(String jsonString, String accessToken) {
        String[] rets;
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        if (UAT_ACCESS_TOKEN.equalsIgnoreCase(accessToken)) {
            rets = genParamSign(UAT_APP_ID, UAT_APP_SECRET, noncestr, version, timestamp, format, interfaceName,
                    null, jsonString, accessToken);
        } else {
            rets = genParamSign(PROD_APP_ID, PROD_APP_SECRET, noncestr, version, timestamp, format, interfaceName,
                    null, jsonString, accessToken);
        }
        return rets[1];
    }

    public static String[] genParamSign(String appid, String appsecret, String noncestr, String version, String timestamp, String format, String interfaceName,
                                        Map<String, Object> queryParams, String jsonString, String accessToken) {
        Map<String, Object> signParams = new HashMap<>();

        Map<String, Object> postParams = new HashMap<>();
        if (queryParams == null) {
            queryParams = new HashMap<>();
        }
        if (jsonString != null && jsonString.length() > 0) {
            try {
                String sortedJson = convertJson(jsonString);
                postParams.put("body", sortedJson);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        Map<String, Object> comonsMap = new HashMap<>();
        comonsMap.put("appid", safeCheck(appid));
        comonsMap.put("noncestr", safeCheck(noncestr));
        comonsMap.put("timestamp", timestamp);
        comonsMap.put("version", safeCheck(version));
        comonsMap.put("appsecret", safeCheck(appsecret));
        comonsMap.put("format", safeCheck(format));
        comonsMap.put("interfaceName", safeCheck(interfaceName));
        comonsMap.put("accessToken", accessToken);

        // 全部进计算参数中
        signParams.putAll(comonsMap);
        signParams.putAll(queryParams);
        signParams.putAll(postParams);

        // 取出所有的key
        Object[] arKey = signParams.keySet().toArray();
        // 对所有的key进行按Ascii码升序排
        Arrays.sort(arKey);
        StringBuffer buf = new StringBuffer();
        for (Object key : arKey) {
            if (buf.length() > 0) {
                buf.append("&");
            }
            // 对原值进行串接
            buf.append(key).append("=").append(safeCheck(signParams.get(key)));
        }
        // 生成SHA1签名
        String sign = sha1(buf.toString());
        // 剔除appsecret
        comonsMap.remove("appsecret");
        // 加入自签名
        queryParams.put("sign", sign);
        // 加入全局参数
        queryParams.putAll(comonsMap);

        return new String[]{sign, map2urlencode(queryParams), jsonString};
    }

    private static String safeCheck(Object o) {
        return o == null ? "" : o.toString();
    }

    /**
     * 对所有key进行application/x-www-form-urlencoded格式的封装
     *
     * @param dataMap
     * @return
     */
    public static String map2urlencode(Map<String, Object> dataMap) {
        StringBuffer buf = new StringBuffer();
        Set<String> namesSet = dataMap.keySet();
        for (String name : namesSet) {
            if (buf.length() > 0) {
                buf.append("&");
            }
            try {
                buf.append(name).append("=").append(URLEncoder.encode(safeCheck(dataMap.get(name)), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return buf.toString();
    }

    public static String sha1(String text) {
        MessageDigest md = null;
        String outStr = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(text.getBytes(StandardCharsets.UTF_8));
            outStr = byteToString(digest);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return outStr;
    }

    private static String byteToString(byte[] digest) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < digest.length; i++) {
            String tempStr = Integer.toHexString(digest[i] & 0xff);
            if (tempStr.length() == 1) {
                buf.append("0").append(tempStr);
            } else {
                buf.append(tempStr);
            }
        }
        return buf.toString().toLowerCase();
    }

    public static String convertJson(String inputJson) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        // 解析输入 JSON
        Map<String, Object> data = objectMapper.readValue(inputJson, Map.class);
        // 创建按顺序的 JSON
        LinkedHashMap<String, Object> orderedJson = new LinkedHashMap<>();
        orderedJson.put("logisticsNo", data.get("logisticsNo"));
        orderedJson.put("requestId", data.get("requestId"));
        orderedJson.put("taskId", data.get("taskId"));
        orderedJson.put("printName", data.get("printName"));
        orderedJson.put("mxEctData", data.get("mxEctData"));
        orderedJson.put("templateUrl", data.get("templateUrl"));
        // 处理 customData
        ArrayNode customDataArray = objectMapper.createArrayNode();
        for (Map<String, Object> item : (List<Map<String, Object>>) data.get("customData")) {
            ObjectNode customDataNode = objectMapper.createObjectNode();
            customDataNode.put("customTemplateUrl", (String) item.get("customTemplateUrl"));
            // 确保 data 字段也转为 Map
            Map<String, Object> dataMap = (Map<String, Object>) item.get("data");
            ObjectNode dataNode = objectMapper.createObjectNode();
            if (dataMap.get("orderId") != null) {
                dataNode.put("orderId", (String) dataMap.get("orderId"));
            }
            if (dataMap.get("productInfo") != null) {
                dataNode.put("productInfo", (String) dataMap.get("productInfo"));
            }
            if (dataMap.get("remark") != null) {
                dataNode.put("remark", (String) dataMap.get("remark"));
            }
            if (dataMap.get("data1") != null) {
                dataNode.put("data1", (String) dataMap.get("data1"));
            }
            if (dataMap.get("data2") != null) {
                dataNode.put("data2", (String) dataMap.get("data2"));
            }
            if (dataMap.get("data3") != null) {
                dataNode.put("data3", (String) dataMap.get("data3"));
            }
            if (dataMap.get("data4") != null) {
                dataNode.put("data4", (String) dataMap.get("data4"));
            }
            if (dataMap.get("data5") != null) {
                dataNode.put("data5", (String) dataMap.get("data5"));
            }
            customDataNode.set("data", dataNode);
            customDataArray.add(customDataNode);
        }
        orderedJson.put("customData", customDataArray);

        // 处理 senderInfo
        ArrayNode senderInfoArray = objectMapper.createArrayNode();
        if (data.get("senderInfo") != null) {
            for (Map<String, Object> item : (List<Map<String, Object>>) data.get("senderInfo")) {
                ObjectNode senderInfoNode = objectMapper.createObjectNode();

                // 确保 address 字段也转为 Map
                Map<String, Object> addressMap = (Map<String, Object>) item.get("address");
                ObjectNode addressNode = objectMapper.createObjectNode();
                addressNode.put("senderProvince", (String) addressMap.get("senderProvince"));
                addressNode.put("senderCity", (String) addressMap.get("senderCity"));
                addressNode.put("senderDistrict", (String) addressMap.get("senderDistrict"));
                addressNode.put("senderAddress", (String) addressMap.get("senderAddress"));
                senderInfoNode.set("address", addressNode);

                // 确保 contact 字段也转为 Map
                Map<String, Object> contactMap = (Map<String, Object>) item.get("contact");
                ObjectNode contactNode = objectMapper.createObjectNode();
                contactNode.put("senderName", (String) contactMap.get("senderName"));
                contactNode.put("sendermobile", (String) contactMap.get("sendermobile"));
                senderInfoNode.set("contact", contactNode);

                senderInfoArray.add(senderInfoNode);
            }
            orderedJson.put("senderInfo", senderInfoArray);
        }
        // 返回格式化的 JSON 字符串
//        return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(orderedJson);
        return objectMapper.writeValueAsString(orderedJson);
    }

}
